package com.mdp.workflow.ru.listener.global;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.mdp.core.entity.Tips;
import com.mdp.core.err.BizException;
import com.mdp.core.query.QueryTools;
import com.mdp.core.utils.BaseUtils;
import com.mdp.micro.client.CallBizService;
import com.mdp.safe.client.entity.User;
import com.mdp.safe.client.utils.LoginUtils;
import com.mdp.workflow.pub.entity.SysUser;
import com.mdp.workflow.pub.service.SysUserService;
import com.mdp.workflow.ru.entity.ProcinstNodeInfo;
import com.mdp.workflow.ru.listener.PushImMsgService;
import com.mdp.workflow.ru.service.ProcinstNodeInfoService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.SequenceFlow;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.common.engine.impl.event.FlowableEntityEventImpl;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.TaskService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * 任务节点前置监听处理类
 * @author: Lu Yang
 * @create: 2019-05-04 20:51
 **/
@Component
public class TaskCreatedListener implements FlowableEventListener {

	Log log=LogFactory.getLog(TaskCreatedListener.class);

	
	@Autowired
	private ProcinstNodeInfoService procinstNodeInfoService;

	@Autowired
	private SysUserService sysUserService;


	@Autowired
    PushImMsgService pushMsgService;



	@Autowired
	CallBizService callBizService;
	
	 public DelegateExecution getExecution(String executionId) {
	        if (executionId != null) {
	            CommandContext commandContext = CommandContextUtil.getCommandContext();
	            if (commandContext != null) {
	                return CommandContextUtil.getExecutionEntityManager(commandContext).findById(executionId);
	            }
	        }
	        return null;
	    }
	

    @Override
    public void onEvent(FlowableEvent event) {
		// TODO Auto-generated method stub
		 // 当前节点任务实体
    	TaskService taskService=CommandContextUtil.getProcessEngineConfiguration().getTaskService();
		FlowableEntityEventImpl eventImpl=(FlowableEntityEventImpl)event;
       TaskEntity taskEntity = (TaskEntity) (eventImpl).getEntity(); 
       DelegateExecution execution=this.getExecution(eventImpl.getExecutionId());
		String procDefId=execution.getProcessDefinitionId();
		FlowElement element=execution.getCurrentFlowElement();
		if(element instanceof UserTask) {
			UserTask task=(UserTask)element;
		
			if(task.hasMultiInstanceLoopCharacteristics()){
				/**
				 * 另附判断结果类中流程引擎自带可用变量：
					1.nrOfInstances 该会签环节中总共有多少个实例
						2.nrOfActiveInstances 当前活动的实例的数量，即还没有 完成的实例数量。
						3.nrOfCompletedInstances 已经完成的实例的数量
						4.nrOfAgree 同意个数
						5.nrOfDisAgree 不同意个数
					 */
				int completedInstance = (int)execution.getVariable("nrOfCompletedInstances");
				int nrOfInstances = (int)execution.getVariable("nrOfInstances"); 
				execution.setVariable("nrOfAgree", 0);
				execution.setVariable("nrOfDisAgree", 0);
				log.debug("completedInstance"+completedInstance);
				return;
			}else {
				Map<String, Object> flowVars = execution.getVariables();
				String isStart = (String) flowVars.get("isStart");
				String processInstanceId = taskEntity.getProcessInstanceId();
				List<ProcinstNodeInfo> nodeInfos = (List<ProcinstNodeInfo>) flowVars.get("nodeInfos");
				if (!flowVars.containsKey("nodeInfos") && !"1".equals(isStart)) {
					nodeInfos = procinstNodeInfoService.getNodeInfosFromCache(processInstanceId);
				} else {
					if ("1".equals(isStart)) {
						this.procinstNodeInfoService.addNodeInfos(processInstanceId, nodeInfos);
					} else {
						this.procinstNodeInfoService.updateNodeInfos(processInstanceId, nodeInfos);
					}
				}
				ProcinstNodeInfo node = null;
				for (ProcinstNodeInfo nodeInfo : nodeInfos) {
					if (nodeInfo.getActId().equals(taskEntity.getTaskDefinitionKey())) {
						node = nodeInfo;
						break;
					}
				}
				if (node != null) {
					if ("1".equals(node.getCandidate())) {//如果是候选类型的节点
						if (StringUtils.hasText(node.getConditions())) {
							User u = LoginUtils.getCurrentUserInfo();
							Map<String, Object> params = BaseUtils.map("hiQueryParams", node.getConditions());
							QueryTools.alias(params,"userid res.userid");
							QueryWrapper<SysUser> ew = QueryTools.initQueryWrapper(SysUser.class, params, "deptid", "postId");
							ew.eq("res.branch_id", u.getBranchId());
							IPage page = QueryTools.initPage(params);
							List<Map<String, Object>> users = sysUserService.selectListMapByWhere(page, ew, params);
							if (users == null || users.size() == 0) {
								throw new BizException("conditions-err", "根据条件表达式寻找任务执行人为0个。请修改条件表达式，减少查询条件，可以查询到更多用户。");
							}
							for (Map<String, Object> user : users) {
								String userid = (String) user.get("userid");
								if (!StringUtils.isEmpty(userid)) {
									pushMsgService.pushTaskMsgToIm(userid, taskEntity.getName(), taskEntity.getName(), (String) execution.getVariable("commentMsg"), (String) execution.getVariable("bizUrl"));
									taskService.addCandidateUser(taskEntity.getId(), userid);
								}
							}
						}
					} else {//如果不是候选节点，则直接赋值给执行人，如果配置了多个，则只取第一个。

						String createUserid = (String) flowVars.get("startUserid");
						String modelAssignee = task.getAssignee();
						if ("1".equals(node.getToCreater()) || (org.springframework.util.StringUtils.hasText(modelAssignee) && modelAssignee.contains("${INITIATOR}"))) {//如果是指向发起人，则将发起人设为该任务执行人
							taskEntity.setAssignee(createUserid);
						} else if (StringUtils.hasText(node.getHxUserids())) {
							taskEntity.setAssignee(node.getHxUserids().split(",")[0]);
						} else if (StringUtils.hasText(node.getConditions())) {
							User u = LoginUtils.getCurrentUserInfo();
							Map<String, Object> params = BaseUtils.map("hiQueryParams", node.getConditions());
							QueryTools.alias(params,"userid res.userid");
							QueryWrapper<SysUser> ew = QueryTools.initQueryWrapper(SysUser.class, params, "deptid", "postId");
							ew.eq("res.branch_id", u.getBranchId());
							IPage page = QueryTools.initPage(params);
							List<Map<String, Object>> users = sysUserService.selectListMapByWhere(page, ew, params);
							if (users == null || users.size() == 0) {
								throw new BizException("conditions-err", "根据条件表达式寻找任务执行人为0个。请修改条件表达式，减少查询条件，可以查询到更多用户。");
							} else {
								taskEntity.setAssignee((String) users.get(0).get("userid"));
							}
						} else {//如果没有配置执行人 启动流程时或者下完成任务时，下一步执行人可能为空，需要做如下特殊处理，启动流程的时候，如果报错(错误码 need-single-assignee)，需要上送 nextAssigneeList，并且赋值给assignee变量
							String assignee = (String) execution.getVariable("assignee");
							String taskAssignee = taskEntity.getAssignee();
							if (StringUtils.isEmpty(modelAssignee)) {
								if (StringUtils.isEmpty(taskAssignee) && StringUtils.isEmpty(assignee)) {
									throw new BizException("need-single-assignee", "请指定下一步执行人");
								} else if (!StringUtils.isEmpty(assignee)) {
									taskEntity.setAssignee(assignee);
								}
							} else if (modelAssignee.contains("${assignee}") && StringUtils.isEmpty(assignee)) {
								throw new BizException("need-single-assignee", "请指定下一步执行人");
							}
							;
						}
					}
					//subscribeTaskEvent
					//如果有上送restUrl，回调restUrl推送审核数据 
					String restUrl = (String) flowVars.get("restUrl");
					String mainTitle = (String) flowVars.get("mainTitle");
					String subscribeTaskEvent = (String) flowVars.get("subscribeTaskEvent");
					String currentUserid = (String) flowVars.get("currentUserid");
					String currentUsername = (String) flowVars.get("currentUsername");
					String startUserid = (String) flowVars.get("startUserid");
					String taskName = taskEntity.getName();
					if (!StringUtils.isEmpty(restUrl) && subscribeTaskEvent != null && subscribeTaskEvent.contains(event.getType().name())) {
						Map<String, Object> paramMap = new HashMap<String, Object>();

						///processInstance.get
						String bizKey = (String) flowVars.get("bizKey");
						String actId = taskEntity.getTaskDefinitionKey();

						String branchId = taskEntity.getTenantId();
						String eventName = event.getType().name();
						String formId = (String) flowVars.get("formId");
						paramMap.putAll(flowVars);
						paramMap.put("procInstId", processInstanceId);
						paramMap.put("startUserid", startUserid);
						paramMap.put("mainTitle", mainTitle);
						paramMap.put("assignee", taskEntity.getAssignee());
						paramMap.put("assigneeName", taskEntity.getAssignee());
						paramMap.put("actId", actId);
						paramMap.put("taskName", taskName);
						paramMap.put("flowBranchId", branchId);
						paramMap.put("bizKey", bizKey);
						paramMap.put("eventName", eventName);
						paramMap.put("modelKey", execution.getProcessDefinitionId());
						if (!StringUtils.isEmpty(formId)) {
							paramMap.put("formId", formId);
						}
						Tips tips = callBizService.postForTips(restUrl, paramMap);
						if (tips.isOk() == false) {
							throw new BizException(tips);
						}
					}
					//pushMsgService.pushMsgToIm(startUserid, "流程【"+mainTitle+"】,任务【"+taskName+"】已由【"+currentUsername+"】提交");
					pushMsgService.pushTaskMsgToIm(taskEntity.getAssignee(), (String) execution.getVariable("mainTitle"), taskEntity.getName(), (String) execution.getVariable("commentMsg"), (String) execution.getVariable("bizUrl"));
				}else{
					throw new BizException("act-node-info-empty",task.getName()+"未配置节点信息");
				}
			}
		}else if(element instanceof SequenceFlow){//如果当前是线条，下一个任务是人工多实例节点，，则从参数配置中看是否配置了默认执行人，如果配置了，把执行人列表设置到流程变量assigneeList中
			SequenceFlow sequenceFlow=(SequenceFlow)element;
			FlowElement element2=sequenceFlow.getTargetFlowElement();
			String processInstanceId=taskEntity.getProcessInstanceId();
			if(element2 instanceof UserTask) {
				UserTask task=(UserTask)element2;
				if(task.hasMultiInstanceLoopCharacteristics()) {
					List<ProcinstNodeInfo> nodeInfos =procinstNodeInfoService.getNodeInfosFromCache(processInstanceId);
					Optional<ProcinstNodeInfo> option =nodeInfos.stream().filter(k->k.getActId().equals(task.getId()) && k.getProcDefId().equals(procDefId)).findAny();
					if(option.isPresent()){
						ProcinstNodeInfo nodeInfoVo=option.get();
						if("1".equals(nodeInfoVo.getToCreater())){
							//无须处理
						}else if("1".equals(nodeInfoVo.getCandidate())){
							if(StringUtils.hasText(nodeInfoVo.getConditions())){
								User u= LoginUtils.getCurrentUserInfo();
								Map<String,Object> params=BaseUtils.map("hiQueryParams",nodeInfoVo.getConditions());
								QueryWrapper<SysUser> ew= QueryTools.initQueryWrapper(SysUser.class,params,"deptid","postId");
								ew.eq("res.branch_id",u.getBranchId());
								QueryTools.alias(params,"userid res.userid");
								IPage page=QueryTools.initPage(params);
								List<Map<String,Object>> users= sysUserService.selectListMapByWhere(page,ew,params);
								List<String> assigneeList=new ArrayList<>();
								if(users.size()>0 ){
									for (Map<String, Object> user : users) {
										String userid=(String) user.get("userid");
										if(StringUtils.isEmpty(userid)) {
											assigneeList.add(userid);
										}
									}
									execution.setVariable("assigneeList", assigneeList);
								}
							}
						}
					}

				}
			}
		}

		
	}

    @Override
    public boolean isFailOnException() {
        return true;
    }

    @Override
    public boolean isFireOnTransactionLifecycleEvent() {
        return false;
    }

    @Override
    public String getOnTransaction() {
        return null;
    }
}